﻿using NewLife;
using NewLife.Data;
using NewLife.Log;
using NewLife.Net;
using NewLife.Net.Handlers;
using NewLife.Serialization;
using System.Collections.Concurrent;
using System.Drawing;
using System.IO.Compression;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;

namespace NetClient;

/// <summary>
/// 监听文件变化类
/// </summary>
public static class LogFile
{
    // 记录读取到的最后一条数据
    public static string lastData = string.Empty;

    // Socket客户端
    public static ISocketClient socketClient;

    /// <summary>
    /// 监听新增文件事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public static void watcher_Created(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"监听到日志文件发生新增：{e.Name}");
        if (!File.Exists(e.FullPath)) return;
        Task.Delay(1000).Wait();
        ServiceLogInfo serviceLogInfo = new ServiceLogInfo (true,e.Name,45,e.FullPath,DateTime.UtcNow.ToString("yy-MM-dd"));
        // 获取数据
        var packet = CollectionFileInfo(serviceLogInfo).Result;

        // 启动Socker客户端
        Init();
        // 打开连接
        SocketOpen();
        // 发送数据
        SocketSendPacket(packet);


        // 使用 FileStream 类来打开指定路径的文件，并创建一个 streamReader 对象以便读取文件
        //using (var streamStream = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        //{
        //    // 是否支持读取操作
        //    if (streamStream.CanRead)
        //    {
        //        // 流读取器
        //        StreamReader sr = new StreamReader(streamStream);
        //        var dataText = string.Empty;

        //        // 是否到达流的末尾
        //        while (!sr.EndOfStream)
        //        {
        //            if (!string.IsNullOrWhiteSpace(sr.ReadLine()))
        //            {
        //                dataText += sr.ReadLine();
        //                dataText += Environment.NewLine;
        //            }
        //        }

        //        // 封装发送消息Dto
        //        var logMessage = new LogFileMessage
        //        {
        //            IsNewFile = true,
        //            FileName = e.Name,
        //            Data = Encoding.UTF8.GetBytes(dataText)
        //        };

        //        var packet = logMessage.CreatePacket();

        //        // 启动Socker客户端
        //        Init();
        //        // 打开连接
        //        SocketOpen();
        //        // 发送数据
        //        SocketSendPacket(packet);

        //        return;
        //    }
        //    else
        //    {
        //        XTrace.Log.Error($"{e.FullPath}不可访问");
        //        return;
        //    }
        //}

    }

    /// <summary>
    /// 监听文件发生变化时间
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public static void watcher_Changed(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"监听到日志发生变动：{e.Name}");

        (sender as FileSystemWatcher).EnableRaisingEvents = false;

        // 确保changed事件可以被重新触发。
        (sender as FileSystemWatcher).EnableRaisingEvents = true;

        // 判断是否更新数据
        // 新增的日志文本信息
        var textBuilder = string.Empty;

        // 使用正则，筛选日志文件
        string strReg = @"\.log\b";

        if (Regex.IsMatch(e.Name, strReg))
        {

            ServiceLogInfo serviceLogInfo = new ServiceLogInfo(true, e.Name, 45, e.FullPath, DateTime.UtcNow.ToString("yy-MM-dd"));
            // 获取数据
            var packet = CollectionFileInfo(serviceLogInfo).Result;

            // 启动Socker客户端
            Init();
            // 打开连接
            SocketOpen();
            // 发送数据
            SocketSendPacket(packet);

            #region
            //lock (lastData)
            //{
            //    FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            //    // 流读取器
            //    StreamReader sr = new StreamReader(fs);
            //    try
            //    {
            //        // 第一次读取，更新lastData
            //        if (lastData == string.Empty)
            //        {
            //            string s = string.Empty;
            //            // 是否到达流的末尾
            //            while (!sr.EndOfStream)
            //            {
            //                // 读取一行并返回一个包含该行内容的字符串。
            //                s = sr.ReadLine();
            //                lastData = s;

            //                if (!string.IsNullOrWhiteSpace(s))
            //                {
            //                    textBuilder += s;
            //                    textBuilder += Environment.NewLine;
            //                }
            //            }
            //        }
            //        // 新增日志数据
            //        else
            //        {
            //            string s = string.Empty;
            //            do
            //            {
            //                s = sr.ReadLine();
            //            } while (s != lastData);
            //            while (!sr.EndOfStream)
            //            {
            //                s = sr.ReadLine();
            //                if (!string.IsNullOrWhiteSpace(s))
            //                {
            //                    textBuilder += s;
            //                    textBuilder += Environment.NewLine;
            //                }
            //                lastData = s;
            //            }
            //        }
            //        Console.WriteLine($"记录的最新一条数据：{lastData}");
            //        // 去除最后一个字符，即换行符
            //        textBuilder = textBuilder.TrimEnd('\r', '\n');
            //        var logMessage = new LogFileMessage
            //        {
            //            IsNewFile = false,
            //            FileName = e.Name,
            //            Data = Encoding.UTF8.GetBytes(textBuilder.ToString())
            //        };
            //        var packet = logMessage.CreatePacket();

            //        // 启动Socker客户端
            //        Init();
            //        // 打开连接
            //        SocketOpen();
            //        SocketSendPacket(packet);

            //        return;
            //    }
            //    catch (Exception ex)
            //    {
            //        //。。。处理错误
            //        return;
            //    }
            //    finally
            //    {
            //        sr.Close();
            //        fs.Close();
            //    }
            //}
            #endregion
        }
    }

    /// <summary>
    /// 创建Socket客户端
    /// </summary>
    public static void Init()
    {
        if (socketClient != null) return;

        var uri = new NetUri("tcp://127.0.0.1:1227");
        //var uri = new NetUri("tcp://::1:1227");
        //var uri = new NetUri("tcp://192.168.1.7:1234");
        var client = uri.CreateRemote();
        client.Log = XTrace.Log;
        client.LogSend = true;
        client.LogReceive = true;
        client.Add<StandardCodec>();
        client.Add<JsonCodec>();
        client.Received += (s, e) =>
        {
            SocketReceived(e);
        };

        socketClient = client;
    }

    /// <summary>
    /// 打开连接
    /// </summary>
    public static void SocketOpen()
    {
        if (socketClient == null) Init();

        socketClient?.Open();
    }

    /// <summary>
    /// 发送字符串数据
    /// </summary>
    /// <param name="message"></param>
    private static void SocketSend(string message)
    {
        if (socketClient == null) SocketOpen();
        XTrace.WriteLine("检测到文件内容有变动：{0}", message);
        socketClient.Send(message);
    }

    /// <summary>
    /// 发送Packet数据
    /// </summary>
    /// <param name="packet"></param>
    private static void SocketSendPacket(Packet packet)
    {
        if (socketClient == null) SocketOpen();
        //XTrace.WriteLine("检测到文件有新增：{0}", packet);
        socketClient?.Send(packet);
    }

    /// <summary>
    /// 发送数据后回调
    /// </summary>
    /// <param name="e"></param>
    private static void SocketReceived(ReceivedEventArgs e)
    {
        if (!(e.Message is Packet pk1))
        {
            XTrace.WriteLine("服务器已收到更新的文件信息：{0}", e.Message);
        }
        else
        {
            XTrace.WriteLine("服务器已收到新增的文件信息：{0}", pk1.ToStr());
        }
    }

    /// <summary>
    /// 销毁
    /// </summary>
    private static void SocketDispose()
    {
        if (socketClient == null) return;

        socketClient.Dispose();
    }

    private static async Task<Packet> CollectionFileInfo(ServiceLogInfo serviceLogInfo)
    {
        return await Task.Run(() =>
        {
            List<byte> fileBytesList = new List<byte>();

            using (FileStream fileStream = new FileStream(serviceLogInfo.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                int bufferSize = 1024 * 10; // 每次读取的缓冲区大小
                byte[] buffer = new byte[bufferSize];
                int bytesRead;

                while ((bytesRead = fileStream.Read(buffer, 0, bufferSize)) > 0)
                {
                    for (int i = 0; i < bytesRead; i++)
                    {
                        fileBytesList.Add(buffer[i]); // 将字节添加到列表中
                    }
                }
            }

            //FileStream fileStream = new FileStream(serviceLogInfo.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);


            // 读取文件内容并转换为 byte[] 数组
            //byte[] fileBytes = fileStream.ReadArray();
            byte[] fileBytes = fileBytesList.ToArray();

            // 输出文件名和文件大小
            Console.WriteLine($"File: {Path.GetFileName(serviceLogInfo.LogName)}, Size: {fileBytes.Length} bytes");

            var logPacketInfo = new LogPacketInfo
            {
                IsNewFile = serviceLogInfo.IsNew,
                FileName = serviceLogInfo.LogName,
                ProgressType = serviceLogInfo.progressType,
                Data = fileBytes
                //Data = Encoding.UTF8.GetBytes(textBuilder.ToString())
            };

            //var packet = logPacketInfo.CreatePacket();

            // 将 LogPacketInfo 对象序列化为 JSON 字符串
            //string logPacketInfoJson = logPacketInfo.ToJson(true);
            string logPacketInfoJson = JsonSerializer.Serialize(logPacketInfo);
            //var pk = Binary.FastWrite(logPacketInfo);

            //var data = GZip(logPacketInfoJson.GetBytes());
            //var data = GZip(Encoding.UTF8.GetBytes(logPacketInfoJson));
            //XTrace.Log.Info($"压缩后：{data.Length}");
            //var packet = new Packet(data);
            //var packet = pk;

            var packet = new Packet(Encoding.UTF8.GetBytes(logPacketInfoJson));

            //var receivedLogPacketInfo = JsonSerializer.Deserialize<LogPacketInfo>(Encoding.UTF8.GetString(packet.Data.ToArray()));

            XTrace.Log.Info($"{logPacketInfo}");

            return Task.FromResult(packet);
        });
    }

    private static byte[] GZip(byte[] jsonBytes)
    {
        XTrace.Log.Info($"压缩前：{jsonBytes.Length}");
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Compress))
            {
                gzipStream.Write(jsonBytes, 0, jsonBytes.Length);
            }
            return memoryStream.ToArray();
        }
    }

    /// <summary>
    /// 服务日志内容
    /// </summary>
    /// <param name="IsNew"></param>
    /// <param name="LogName"></param>
    /// <param name="progressType"></param>
    /// <param name="Path"></param>
    /// <param name="CreateDateString"></param>
    public record ServiceLogInfo(bool IsNew, string LogName, int progressType, string Path, string CreateDateString);

    /// <summary>
    /// Packet包裹数据
    /// </summary>
    public record LogPacketInfo
    {
        /// <summary>
        /// 是否新增文件
        /// </summary>
        public bool IsNewFile { get; set; }

        /// <summary>
        /// 文件名称
        /// </summary>
        public required string FileName { get; set; }

        /// <summary>
        /// 进程
        /// </summary>
        public required int ProgressType { get; set; }

        /// <summary>
        /// 文件具体内容
        /// </summary>
        public byte[]? Data { get; set; }
    }

 }